<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <div id="nav">
      <a href="/page1">page1</a>
      <a href="/page2">page2</a>
      <a href="/page3">page3</a>
    </div>
    <div id="container"></div>
    <script>
      /**
       * 在 HTML5 的规范中，history 新增了以下几个 API：
       *  history.pushState();         // 添加新的状态到历史状态栈
          history.replaceState();      // 用新的状态代替当前状态
          history.state                // 返回当前状态对象
          history.pushState() 和 history.replaceState() 均接收三个参数（state, title, url）
            state：合法的 Javascript 对象，可以用在 popstate 事件中
            title：现在大多浏览器忽略这个参数，可以直接用 null 代替
            url：任意有效的 URL，用于更新浏览器的地址栏
      */
    //  histroy 需要通过a标签跳转，或者pushState跳转，或者通过浏览器的前进后退
    class HistoryRouter {
        constructor() {
          //用于存储不同path值对应的回调函数
          this.routers = {};
          this.pathname = location.pathname
          this.listenPopState()
          this.listenLink()
        }
        load() {
          //因为我们这个是文件打开的，所以pathname会记录文件路径，所以需要处理一下
          let path = location.pathname.split('/')[4]
          this.dealPathHandler(path)
        }
        // 监听popstate事件，也就是浏览器的前进和后退
        listenPopState() {
          //监听 popstate 用于处理前进后退时调用对应的回调函数
          window.addEventListener('popstate',(e) => {
            // e.state里面存储着pushState里面的第一个参数值
            let state = e.state || {}
            let path = state.path || ''
            this.dealPathHandler(path)
          })
        }
        // 监听A链接跳转
        listenLink() {
          window.addEventListener('click',(e)=>{
            let dom = e.target
            if(dom.tagName.toUpperCase()==='A'){
              e.preventDefault()
              this.push(dom.getAttribute('href'))
            }
          })
        }
        //用于注册每个视图
        register(path, callback = function () {}) {
          this.routers[path] = callback;
        }
        //用于注册首页
        registerIndex(callback = function () {}) {
          this.routers["/"] = callback;
        }
        //用于处视图未找到的情况
        registerNotFound(callback = function () {}) {
          this.routers["404"] = callback;
        }
        //用于处理异常情况
        registerError(callback = function () {}) {
          this.routers["error"] = callback;
        }
        //跳转到path路径
        push(path) {
          let path1 = this.pathname + path
          history.pushState({path},null,path1)
          this.dealPathHandler(path)
        }
        replace(path) {
          let path1 = this.pathname + path
          history.replaceState({path:path1},null,path1)
          this.dealPathHandler(path)
        }
        dealPathHandler(path) {
          let handler
          if(!this.routers[path]) {
            handler = this.routers['404']
          }else {
            handler = this.routers[path]
          }
          if(!path) {
            handler = this.routers['/']
          }
          try {
            handler.call(this)
          } catch (error) {
            this.routers['error'].call(this)
          }
        }
      }
    let container = document.getElementById('container')
    let router = new HistoryRouter()
    router.registerIndex(function(){ container.innerHTML = '我是首页'})
    router.register('/page1',function() {container.innerHTML='我是page1'})
    //注册其他视图回到函数
    router.register('/page2', () => container.innerHTML = '我是page2');
    router.register('/page3', () => container.innerHTML = '我是page3');
    router.register('/page4', () => {
        throw new Error('抛出一个异常')
    });
    router.registerNotFound(function(){container.innerHTML = '404'})
    router.load()
    // window.addEventListener('popState',function(){
    //   console.log(22222);
    // })
    </script>
  </body>
</html>
